package ru.spbau.database.group3.index;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import ru.spbau.database.group3.engine.Column;
import ru.spbau.database.group3.filesAndAccess.Record;

public class IndexKeyType implements Serializable, Comparator<Record> {

	private final Column[] columns;
	private List<Column> relationColumns;

	public Column[] getColumns() {
		return columns;
	}

	public IndexKeyType(Column column, List<Column> relationColumns) {
		columns = new Column[1];
		columns[0] = column;
		this.relationColumns = relationColumns;
	}

	public IndexKeyType(Set<Column> columns, List<Column> relationColumns) {
		this.relationColumns = relationColumns;
		this.columns = columns.toArray(new Column[columns.size()]);
		Arrays.sort(this.columns, ColumnComparator.getInstance());
		int offset = 0;
		for (int i = 0; i < this.columns.length; ++i) {
			Column c = this.columns[i];
			this.columns[i] = new Column(c.getName(), offset, c.getType());
			offset += c.getType().size();
		}
	}

	public IndexKeyType(List<Column> columns, List<Column> relationColumns) {
		this.relationColumns = relationColumns;
		this.columns = columns.toArray(new Column[columns.size()]);
		Arrays.sort(this.columns);
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof IndexKeyType) {
			IndexKeyType arg = (IndexKeyType) o;
			if (arg.columns.length != columns.length) {
				return false;
			}
			for (int i = 0; i < columns.length; ++i) {
				if (!columns[i].equals(arg.columns[i])) {
					return false;
				}
			}
			return true;
		} else {
			return false;
		}
	}

	@Override
	public int hashCode() {
		int hashCode = 1;
		for (int i = 0; i < columns.length; ++i) {
			hashCode *= columns[i].hashCode();
		}
		return hashCode;
	}

	@Override
	public int compare(Record o1, Record o2) {
		for (int i = 0; i < columns.length; ++i) {
			Column currentColumn = columns[i];
			int currentColumnCmp = 0;
			for (Column relationColumn : relationColumns) {
				if (currentColumn.equals(relationColumn)) {
					try {
						Object obj1 = o1.getColumnValue(currentColumn);
						Object obj2 = o2.getColumnValue(relationColumn);
						currentColumnCmp = currentColumn.getType().compareTo(
								obj1, obj2);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			if (currentColumnCmp != 0) {
				return currentColumnCmp;
			}
		}
		return 0;
	}
}
